package gui;

import java.awt.*;
import java.awt.font.*;
import java.awt.geom.*;
import java.math.BigDecimal;

import javax.swing.*;

public class CostFunctionGraph extends JPanel {

	private Double[] data;

	public CostFunctionGraph(Double[] doubles) {

		data = doubles;
		this.setBackground(Color.white);
	}

	final int PAD = 20;

	protected void paintComponent(Graphics g) {
		super.paintComponent(g);
		Graphics2D g2 = (Graphics2D) g;
		g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
				RenderingHints.VALUE_ANTIALIAS_ON);
		int w = getWidth();
		int h = getHeight();
		// Draw ordinate.
		g2.draw(new Line2D.Double(PAD, PAD, PAD, h - PAD));
		// Draw abcissa.
		g2.draw(new Line2D.Double(PAD, h - PAD, w - PAD, h - PAD));
		// Draw labels.
		Font font = g2.getFont();
		FontRenderContext frc = g2.getFontRenderContext();
		LineMetrics lm = font.getLineMetrics("0", frc);
		float sh = lm.getAscent() + lm.getDescent();
		// Ordinate label.
		String s = "Power Cost";
		float sy = PAD + ((h - 2 * PAD) - s.length() * sh) / 2 + lm.getAscent();
		for (int i = 0; i < s.length(); i++) {
			String letter = String.valueOf(s.charAt(i));
			float sw = (float) font.getStringBounds(letter, frc).getWidth();
			float sx = (PAD - sw) / 2;
			g2.drawString(letter, sx, sy);
			sy += sh;
		}
		// Abcissa label.
		s = "Iterations";
		sy = h - PAD + (PAD - sh) / 2 + lm.getAscent();
		float sw = (float) font.getStringBounds(s, frc).getWidth();
		float sx = (w - sw) / 2;
		g2.drawString(s, sx, sy);
		// Draw lines.
		double xInc = (double) (w - 2 * PAD) / (data.length - 1);
		double scale = (double) (h - 2 * PAD) / getMax();
		g2.setPaint(Color.blue.darker());
		for (int i = 0; i < data.length - 1; i++) {
			double x1 = PAD + i * xInc;
			double y1 = h - PAD - scale * data[i];
			double x2 = PAD + (i + 1) * xInc;
			double y2 = h - PAD - scale * data[i + 1];
			g2.draw(new Line2D.Double(x1, y1, x2, y2));
		}
		// Mark data points.
		g2.setPaint(Color.red);
		for (int i = 0; i < data.length; i++) {
			double x = PAD + i * xInc;
			double y = h - PAD - scale * data[i];
			int flag = 0;

			if (y == h - PAD - scale * getMin()) {
				g2.setPaint(Color.green.darker());
				g2.fill(new Ellipse2D.Double(x - 2, y - 2, 10, 10));
				g2.setPaint(Color.black.darker());
				/* draw the min cost */
				if (flag == 0) {
					BigDecimal finalBd = new BigDecimal(getMin());
					BigDecimal initialBd = new BigDecimal(data[0]);
					finalBd = finalBd.setScale(5, BigDecimal.ROUND_HALF_UP);
					initialBd = initialBd.setScale(5, BigDecimal.ROUND_HALF_UP);
					g2.drawString(
							("  The initial floorplan cost is : " + String
									.valueOf(initialBd))
									+ (",      The minimal floorplan cost that was found is (Green points): " + String
											.valueOf(finalBd)), (float) 30,
							(float) y + 20);
					flag++;
				}
			}

			else {
				g2.setPaint(Color.red);
				g2.fill(new Ellipse2D.Double(x - 2, y - 2, 4, 4));
			}
		}

	}

	private double getMax() {
		double max = -Double.MAX_VALUE;
		for (int i = 0; i < data.length; i++) {
			if (data[i] > max)
				max = data[i];
		}
		return max;
	}

	private double getMin() {
		double min = data[0];

		for (int i = 0; i < data.length; i++) {
			if (data[i] < min)
				min = data[i];
		}
		return min;
	}
}